package com.kz.bot.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

public class MartinCalculation {

    /**
     * 计算马丁分档卖出百分比和累计卖出百分比
     * @param initVolumePercent 初始卖出百分比 (例如 0.1 = 10%)
     * @param stepLength 每次涨幅百分比 (例如 0.02 = 2%)
     * @param volumeMartin 马丁系数 (例如 1.2 = 每次卖出量增加 20%)
     * @param priceMartin 价格马丁系数 (例如 1.1 = 每次价格涨幅增加 10%)
     */
    public static void calculation(BigDecimal initVolumePercent, BigDecimal stepLength, BigDecimal volumeMartin, BigDecimal priceMartin) {

        // 保存每次卖出百分比
        List<BigDecimal> sellList = new ArrayList<>();
        // 保存每次累计卖出百分比
        List<BigDecimal> totalSellList = new ArrayList<>();

        BigDecimal currentSellPercent = initVolumePercent; // 当前这次卖出的百分比
        BigDecimal totalSellPercent = BigDecimal.ZERO;     // 累计卖出的百分比

        int step = 0;

        while (totalSellPercent.compareTo(BigDecimal.ONE) < 0) {
            step++;

            // 累加卖出量
            totalSellPercent = totalSellPercent.add(currentSellPercent);

            // 如果累计大于 1，调整最后一次卖出量
            if (totalSellPercent.compareTo(BigDecimal.ONE) > 0) {
                currentSellPercent = currentSellPercent.subtract(totalSellPercent.subtract(BigDecimal.ONE));
                totalSellPercent = BigDecimal.ONE;
            }

            // 保存到集合
            sellList.add(currentSellPercent.setScale(4, RoundingMode.HALF_UP));
            totalSellList.add(totalSellPercent.setScale(4, RoundingMode.HALF_UP));

            // 达到 100% 仓位后停止
            if (totalSellPercent.compareTo(BigDecimal.ONE) >= 0) {
                break;
            }

            // 计算下一次卖出百分比
            currentSellPercent = currentSellPercent.multiply(volumeMartin);
        }

        // 输出结果
        System.out.println("每次卖出百分比集合: " + sellList);
        System.out.println("每次累计卖出百分比集合: " + totalSellList);
    }

    /**
     * 计算最终全部卖出所需的累计涨幅
     *
     * @param initVolumePercent 初始卖出百分比 (例如 0.1 = 10%)
     * @param stepLength 每次涨幅百分比 (例如 0.02 = 2%)
     * @param volumeMartin 马丁系数 (例如 1.2 = 每次卖出量增加20%)
     * @param priceMartin 价格马丁系数 (例如 1.1 = 每次价格涨幅增加 10%)
     * @return 最终累计涨幅百分比
     */
    public static BigDecimal calculateFinalTotalGrowth(BigDecimal initVolumePercent,
                                                       BigDecimal stepLength,
                                                       BigDecimal volumeMartin,
                                                       BigDecimal priceMartin) {

        BigDecimal currentSellPercent = initVolumePercent; // 当前这次卖出的百分比
        BigDecimal totalSellPercent = BigDecimal.ZERO;     // 累计卖出的百分比
        int stepCount = 0;                                 // 卖出的次数
        BigDecimal totalGrowth = BigDecimal.ZERO;          // 累计涨幅

        while (totalSellPercent.compareTo(BigDecimal.ONE) < 0) {
            stepCount++;

            totalSellPercent = totalSellPercent.add(currentSellPercent);

            // 如果最后一次超过1，则修正
            if (totalSellPercent.compareTo(BigDecimal.ONE) > 0) {
                totalSellPercent = BigDecimal.ONE;
            }

            // 计算当前档位的实际涨幅，并累加到总涨幅中
            // 涨幅 = 初始涨幅 * 价格马丁系数的 (stepCount-1) 次方
            BigDecimal currentPriceStep = stepLength.multiply(MathCalculationUtil.pow(priceMartin, BigDecimal.valueOf(stepCount - 1), 10));
            totalGrowth = totalGrowth.add(currentPriceStep);

            if (totalSellPercent.compareTo(BigDecimal.ONE) >= 0) {
                break;
            }

            // 下一次卖出量 = 当前卖出量 * 马丁系数
            currentSellPercent = currentSellPercent.multiply(volumeMartin);
        }

        return totalGrowth.setScale(4, RoundingMode.HALF_UP);
    }

    /**
     * 计算资金收益涨幅
     *
     * @param initVolumePercent 初始卖出量占总持仓比例 (如0.1表示10%)
     * @param stepLength 每次价格上涨幅度 (如0.02表示2%)
     * @param volumeMartin 马丁系数 (每一档卖出量 = 上一档卖出量 * volumeMartin)
     * @param priceMartin 价格马丁系数 (例如 1.1 = 每次价格涨幅增加 10%)
     * @return BigDecimal 资金涨幅（如0.15表示资金增长15%）
     */
    public static BigDecimal calculateFinalCapitalGrowth(BigDecimal initVolumePercent,
                                                         BigDecimal stepLength,
                                                         BigDecimal volumeMartin,
                                                         BigDecimal priceMartin) {

        // 初始价格假设为1（相对值，计算相对涨幅即可）
        BigDecimal initialPrice = BigDecimal.ONE;

        BigDecimal currentSellPercent = initVolumePercent; // 当前卖出的币量占比
        BigDecimal totalSellPercent = BigDecimal.ZERO;     // 累计卖出比例
        int round = 0; // 当前卖出的档位次数

        BigDecimal totalRevenue = BigDecimal.ZERO; // 总资金收入
        BigDecimal currentPrice = initialPrice;    // 当前卖出的价格

        while (totalSellPercent.compareTo(BigDecimal.ONE) < 0) {
            round++;

            // 如果最后一次卖出超过 100%，只卖出剩余部分
            BigDecimal remainingPercent = BigDecimal.ONE.subtract(totalSellPercent);
            BigDecimal actualSellPercent = currentSellPercent.min(remainingPercent);

            // 计算当前档位的价格涨幅
            BigDecimal currentPriceStep = stepLength.multiply(MathCalculationUtil.pow(priceMartin, BigDecimal.valueOf(round - 1), 10));

            // 更新当前卖出的价格
            currentPrice = currentPrice.multiply(BigDecimal.ONE.add(currentPriceStep));

            // 当前卖出获得的资金 = 卖出数量 * 当前价格
            BigDecimal revenue = actualSellPercent.multiply(currentPrice);
            totalRevenue = totalRevenue.add(revenue);

            // 更新累计卖出比例
            totalSellPercent = totalSellPercent.add(actualSellPercent);

            if (totalSellPercent.compareTo(BigDecimal.ONE) >= 0) {
                break;
            }

            // 下一次卖出量 = 当前卖出量 * 马丁系数
            currentSellPercent = currentSellPercent.multiply(volumeMartin);
        }

        // 初始资金 = 1 总持仓 * 初始价格
        BigDecimal initialCapital = BigDecimal.ONE.multiply(initialPrice);

        // 资金收益涨幅 = (卖出后资金 - 初始资金) / 初始资金
        return totalRevenue.subtract(initialCapital)
                .divide(initialCapital, 4, RoundingMode.HALF_UP);
    }


    /**
     * 计算最终全部卖出后的加权平均卖出价格
     *
     * @param initVolumePercent 初始卖出量占总持仓比例 (如0.1表示10%)
     * @param stepLength 每次价格上涨幅度 (如0.02表示2%)
     * @param volumeMartin 马丁系数 (每一档卖出量 = 上一档卖出量 * volumeMartin)
     * @param priceMartin 价格马丁系数 (例如 1.1 = 每次价格涨幅增加 10%)
     * @return BigDecimal 最终加权平均卖出价格
     */
    public static BigDecimal calculateFinalAverageSellPrice(BigDecimal initVolumePercent,
                                                            BigDecimal stepLength,
                                                            BigDecimal volumeMartin,
                                                            BigDecimal priceMartin) {
        // 初始价格假设为1，用于计算相对价格
        BigDecimal initialPrice = BigDecimal.ONE;

        BigDecimal currentSellPercent = initVolumePercent; // 当前卖出的币量占比
        BigDecimal totalSellPercent = BigDecimal.ZERO;     // 累计卖出比例
        int round = 0;                                     // 当前卖出的档位次数

        BigDecimal totalRevenue = BigDecimal.ZERO; // 总资金收入
        BigDecimal currentPrice = initialPrice;    // 当前卖出的价格

        while (totalSellPercent.compareTo(BigDecimal.ONE) < 0) {
            round++;

            BigDecimal remainingPercent = BigDecimal.ONE.subtract(totalSellPercent);
            BigDecimal actualSellPercent = currentSellPercent.min(remainingPercent);

            // 计算当前档位的价格涨幅
            BigDecimal currentPriceStep = stepLength.multiply(MathCalculationUtil.pow(priceMartin, BigDecimal.valueOf(round - 1), 10));

            // 更新当前卖出的价格
            currentPrice = currentPrice.multiply(BigDecimal.ONE.add(currentPriceStep));

            // 计算当前卖出获得的资金
            BigDecimal revenue = actualSellPercent.multiply(currentPrice);
            totalRevenue = totalRevenue.add(revenue);

            // 更新累计卖出比例
            totalSellPercent = totalSellPercent.add(actualSellPercent);

            if (totalSellPercent.compareTo(BigDecimal.ONE) >= 0) {
                break;
            }

            // 计算下一次卖出量
            currentSellPercent = currentSellPercent.multiply(volumeMartin);
        }

        // 最终的平均卖出价格 = 总卖出资金 / 总卖出量
        // 因为总卖出量假设为1（100%），所以最终均价就等于总卖出资金
        return totalRevenue.setScale(4, RoundingMode.HALF_UP);
    }


    public static void main(String[] args) {
        // 初始百分比
        BigDecimal initVolumePercent = new BigDecimal("0.1");
        // 每次涨幅
        BigDecimal stepLength = new BigDecimal("0.01");
        // 卖出量马丁系数
        BigDecimal volumeMartin = new BigDecimal("1.2");
        // 价格马丁系数
        BigDecimal priceMartin = new BigDecimal("1.2");

        // 计算卖出百分比和累计卖出百分比
        calculation(initVolumePercent, stepLength, volumeMartin, priceMartin);

        // 计算卖飞最终涨幅
        BigDecimal growth = calculateFinalTotalGrowth(initVolumePercent, stepLength, volumeMartin, priceMartin);
        System.out.println("最终币价涨幅:" + growth);

        BigDecimal capitalGrowth = calculateFinalCapitalGrowth(initVolumePercent, stepLength, volumeMartin, priceMartin);
        System.out.println("最终累计收益:" + capitalGrowth);

        BigDecimal initPrice = new BigDecimal("232.43");
        BigDecimal penetrationPrice = BigDecimal.ONE.add(growth).multiply(initPrice);
        System.out.println("穿仓价:" + penetrationPrice);


    }
}
